import { Button, Empty, Input, Select, Table } from '@arco-design/web-react';
import { HasPermission, checkPermission } from '@src/components/ability';
import { MenuTypes } from '@src/components/mainNavBar';
import SearchBar from '@src/components/searchBar';
import { IconAdd, IconDelete, IconNameType, SVGIcon } from '@src/components/svg/svgIcon';
import React, { useEffect, useState } from 'react';
import { shallowEqual, useSelector } from 'react-redux';
import { AppStore } from '../../../types';
import { dictTag } from '@src/components/tableColumn';
import TextButton from '@src/components/textButton';
import main from '../../../main';
import useDict, { dictDataOptions } from '../../../utils/dict';
import usePageUtils from '../../../utils/pageUtils';
import { clearEmptyKey, onKeyEnter } from '../../../utils/utils';
import MenuDetailPage from './menuDetailPage';
import { Menu } from './types';

interface Props {
  currentRouteRecord: MenuTypes;
}

const model = 'system';
const table = 'menu';

// 菜单状态
const SYS_SHOW_HIDE = 'sys_show_hide';
const SYS_NORMAL_DISABLE = 'sys_normal_disable';
export default function MenuListPage({ currentRouteRecord }: Props) {
  const pageUtils = usePageUtils({ model, table, type: 'list' });
  // 当前页面选中的数据列表
  const [tabSelectRows, setTabSelectRows] = useState<Menu[]>([]);

  const dictDatas = useDict(SYS_SHOW_HIDE, SYS_NORMAL_DISABLE);
  /// 展开的行
  const [expKeys, setExpKeys] = useState<Array<string | number>>([]);

  const [detailId, setDetailId] = useState<string | number | undefined>();
  const [parentId, setParentId] = useState<number | undefined>();
  /// ---------------搜索栏数据 --按页面要求修改------------
  const [menuName, setMenuName] = useState(pageUtils.params?.menuName ?? '');
  const [status, setStatus] = useState(pageUtils.params?.status ?? '');
  ///----------------------------------------

  // 当前页需要的数据
  const list = useSelector((state: AppStore) => state.list[pageUtils.stateKey], shallowEqual);

  // 创建请求参数 及检索key 按页面要求修改
  function createParams() {
    return clearEmptyKey({ menuName, status, orderByColumn: 'orderNum', isAsc: 'desc' });
  }
  // 需要随时刷新 创建参数的方法
  useEffect(() => {
    pageUtils.setFun(createParams);
  }, [createParams]); // eslint-disable-line

  // 页面初始化时请求数据
  useEffect(() => {
    pageUtils.handleRefreshData();
    main.setPageNum(pageUtils.pageTag, 999);
  }, []); //eslint-disable-line

  // 搜索
  function handleSearch() {
    setTabSelectRows([]);
    pageUtils.handleSearch();
  }

  // 重置
  function handleReset() {
    setTabSelectRows([]);
    setMenuName('');
    setStatus('');
    pageUtils.handleReset({ orderByColumn: 'orderNum', isAsc: 'desc' });
  }

  // 创建
  function handleCreate(record?: Menu) {
    setParentId(record?.menuId);
    setDetailId('create');
  }

  // 修改 操作列内的修改
  function handleEdit(record?: Menu) {
    setDetailId(record?.menuId ?? 'create');
  }
  // 列表项双击事件 一般是进详情
  function handleDoubleClick(record: Menu) {
    let hasPermission = checkPermission('system:menu:edit');
    if (hasPermission) {
      setDetailId(record?.menuId);
    }
  }

  // 删除
  async function handleDelete(record?: Menu) {
    let datas = record ? [record] : tabSelectRows || [];
    pageUtils.handleDelete(datas.map((i) => i.menuId!));
  }

  // 列表项有选择变动
  function handleTabSelectChange(selectedRowKeys: React.Key[], selectedRows: Menu[]) {
    setTabSelectRows(selectedRows);
  }

  ///-----------额外数据 / 方法-------------------
  function findAllKeys(list: Menu[]) {
    let _list: Array<string | number> = [];
    list.forEach((i) => {
      if (i.children) {
        _list.push(i.key!);
        _list = _list.concat(findAllKeys(i.children));
      }
    });
    return _list;
  }
  function handleAllExpand(list: Menu[]) {
    let _list: Array<string | number> = [];
    if (expKeys.length < list.length) {
      _list = findAllKeys(list);
    }
    setExpKeys(_list);
  }
  ///-------------------------------------

  let dataSource: Menu[] = list?.results || [];
  let map: { [x: string]: Menu } = {};
  // 组合数据 先把所有数据都放入map
  dataSource.forEach((i) => {
    let key = (i.menuId ?? '').toString();
    map[key] = Object.assign({}, i, { children: [], key: i.menuId!.toString() });
  });
  // 再按parent组合到children内
  Object.keys(map).forEach((i) => {
    let data = map[i];
    let key = (data.parentId ?? '').toString();
    if (Object.keys(map).includes(key)) {
      map[key].children!.push(data);
    }
  });
  let t: Menu[] = [];
  Object.keys(map).forEach((k) => {
    let data = map[k];
    if ((data.children ?? []).length <= 0) {
      delete data.children;
    } else {
      data.children = data.children!.sort((a, b) => (a.orderNum ?? 0) - (b.orderNum ?? 0));
    }
    if (!data.parentId || !map[data.parentId]) {
      t.push(data);
    }
  });
  dataSource = t.sort((a, b) => (a.orderNum ?? 0) - (b.orderNum ?? 0));
  // 定义表格内的列
  const columns = [
    {
      title: '菜单名称',
      dataIndex: 'menuName',
      key: 'menuName',
    },
    {
      title: '排序',
      dataIndex: 'orderNum',
      key: 'orderNum',
    },
    {
      title: '图标',
      dataIndex: 'icon',
      key: 'icon',
      render: (v: IconNameType) => <SVGIcon type={v} className="font-20" />,
    },
    {
      title: '权限标识',
      dataIndex: 'perms',
      key: 'perms',
    },
    {
      title: '菜单状态',
      dataIndex: 'status',
      key: 'status',
      render: (v: string) => dictTag(v, dictDatas[SYS_NORMAL_DISABLE]),
    },
    {
      title: '显示状态',
      dataIndex: 'visible',
      key: 'visible',
      render: (v: string) => dictTag(v, dictDatas[SYS_SHOW_HIDE]),
    },
    {
      title: '创建时间',
      dataIndex: 'createTime',
      key: 'createTime',
    },
    {
      title: '操作',
      render: (_: any, record: Menu) => (
        <div className="d-flex-r jc-start text-primary-color">
          <TextButton text="新增" permission={['system:menu:add']} onClick={() => handleCreate(record)} />
          <TextButton text="编辑" permission={['system:menu:edit']} onClick={() => handleEdit(record)} />
          <TextButton text="删除" red permission={['system:menu:remove']} onClick={() => handleDelete(record)} />
        </div>
      ),
    },
  ];

  return (
    <div className="page list-page menu-list-page">
      <SearchBar onConfirm={handleSearch} onReset={handleReset}>
        <Input
          allowClear
          className="mr-20 mb-20 search-input"
          placeholder="菜单名称"
          value={menuName}
          onKeyUp={onKeyEnter(handleSearch)}
          onChange={(e) => setMenuName(e)}
        />
        <Select
          className="mr-20 mb-20 search-select"
          allowClear
          placeholder="菜单状态"
          options={dictDataOptions(dictDatas[SYS_NORMAL_DISABLE])}
          value={!status ? undefined : status}
          onChange={(v: string) => setStatus(v)}
        />
      </SearchBar>
      <div className="page-content m-20">
        <div className="action-bar">
          <div className="flex-1" />
          <Button icon={<IconAdd />} className="ml-20" type="outline" onClick={() => handleAllExpand(dataSource)}>
            展开/折叠
          </Button>
          <HasPermission permission={['system:menu:add']}>
            <Button icon={<IconAdd />} className="ml-20" type="outline" onClick={() => handleEdit()}>
              新增
            </Button>
          </HasPermission>
          <HasPermission permission={['system:menu:remove']}>
            <Button
              icon={<IconDelete />}
              className="ml-20"
              type="primary"
              status="danger"
              onClick={() => handleDelete()}
            >
              删除
            </Button>
          </HasPermission>
        </div>
        <Table
          expandedRowKeys={expKeys}
          className="table"
          rowSelection={{ type: 'checkbox', onChange: handleTabSelectChange }}
          data={dataSource}
          columns={columns}
          pagination={false}
          loading={!list || (list?.fetching && !list?.loaded)}
          noDataElement={<Empty description={list?.error ?? '暂无数据'} />}
          onExpand={(record) => {
            let _tmp: Array<string | number> = ([] as Array<string | number>).concat(expKeys);
            if (_tmp.includes(record.key!)) {
              _tmp.splice(_tmp.indexOf(record.key!, 1));
            } else {
              _tmp.push(record.key!);
            }
            setExpKeys(_tmp);
          }}
          onRow={(record: Menu) => ({
            onDoubleClick: () => handleDoubleClick(record),
          })}
        />
      </div>
      {detailId && (
        <MenuDetailPage
          parentId={parentId}
          id={detailId.toString()}
          onCancel={(v?: boolean) => {
            setDetailId(undefined);
            setParentId(undefined);

            if (v) {
              pageUtils.handleRefreshData({ forceRefresh: true });
            }
          }}
        />
      )}
    </div>
  );
}
